#include "vector3.h"

Vector3::Vector3(){
	this->x = 0;
	this->y = 0;
	this->z = 0;
}


Vector3::Vector3(float x, float y, float z){
	this->x = x;
	this->y = y;
	this->z = z;
}

Vector3::Vector3( const Vector3 & v)
{
	x = v.x;
	y = v.y;
	z = v.z;
}

Vector3 Vector3::operator*(float mul){
	Vector3 result;
	result.x = this->x * mul;
	result.y = this->y * mul;
	result.z = this->z * mul;
	return result;

}

bool Vector3::operator==(Vector3& v)
{
	return (this->x == v.x && this->y == v.y && this->z == v.z);
}

Vector3 Vector3::operator+(Vector3& v){
	Vector3 result;
	result.x = this->x + v.x;
	result.y = this->y + v.y;
	result.z = this->z + v.z;
	return result;
}

Vector3 Vector3::operator/(float div){
	Vector3 result;
	result.x = this->x/div;
	result.y = this->y/div;
	result.z = this->z/div;
	return result;
}

Vector3 Vector3::operator-(Vector3& v){
	Vector3 result;
	result.x = this->x - v.x;
	result.y = this->y - v.y;
	result.z = this->z - v.z;
	return result;
}

float Vector3::getCord(int pos){
	if(pos == 0)
		return x;
	else if(pos == 1)
		return y;
	else
		return z;
}

void Vector3::setCord(int pos, float val){
	if(pos == 0)
		x = val;
	else if(pos == 1)
		y = val;
	else
		z = val;
}

Vector3 Vector3::normalize(){
	Vector3 result;
	if(this->magnitude() == 0){
		return result;
	}
	result.x = this->x/this->magnitude();
	result.y = this->y/this->magnitude();
	result.z = this->z/this->magnitude();
	return result;
}

float Vector3::magnitude(){
	return sqrt(pow(x,2) + pow(y,2) + pow(z,2));
}

float Vector3::dotProduct(Vector3 b){
	return x * b.x + y * b.y + z * b.z;
}

float Vector3::getAngle(Vector3 b){
	return acos(this->dotProduct(b)/(this->magnitude() * b.magnitude()));
}

Vector3 Vector3::crossProduct(Vector3 b){
	float x, y, z;
	x = this->y * b.z - this->z * b.y;
	y = this->z * b.x - this->x * b.z;
	z = this->x * b.y - this->y * b.x;
	return Vector3(x, y, z);
}


Vector3 Vector3::projectAtoB(Vector3 b){
	return b * ((this->dotProduct(b))/b.dotProduct(b));
}

void Vector3::printVectors(string in, ...){
	Vector3 tmp;

	stringstream ss (stringstream::in | stringstream::out);

	va_list args;
	string final = "";

	va_start(args, in);

	//looks for places where vectors need to be inserted and adds them to string
	for(int i = 0; i < (int) in.length(); i++){
		if(in.at(i) == '%'){
			try{
				if(in.at(i + 1) == 'v'){
					tmp = va_arg(args, Vector3);
					final += "(";
					ss << tmp.getCord(0);
					final += ss.str();
					ss.str("");
					final += ", ";
					ss << tmp.getCord(1);
					final += ss.str();
					ss.str("");
					final += ", ";
					ss << tmp.getCord(2);
					final += ss.str();
					ss.str("");
					final += ")";
					i++;
				}
				else{
					final+= in.at(i);
				}
			}
			//Catches cases where number of args doesn't match %v's
			catch(int e){
				va_end(args);
				cout << "Inalid Input.  Make sure types match. " << e <<  endl;
				return;
			}
		}
		else{
			final+= in.at(i);
		}
	}
	va_end(args);
	cout << final << endl;
}